/*
 * @Author: didididijiajiajia 11643763+didididijiajiajia@user.noreply.gitee.com
 * @Date: 2023-08-23 17:19:55
 * @LastEditors: didididijiajiajia 11643763+didididijiajiajia@user.noreply.gitee.com
 * @LastEditTime: 2023-09-02 18:11:46
 * @FilePath: \vue低代码101-111\low_code\src\utils\useCommand.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { onUnmounted } from "vue";
import { events } from "./event";
import deepcopy from "deepcopy"
import { extractProperty } from './index.js'
export function useCommand(data, focusData) {
    const state = { //前进后退指针
        current: -1, //前进后退索引值
        queue: [],//存放所有的操作命令
        commands: {},//制作命令和执行一个功能映射表
        commandArray: [],//存放命令
        destoryArray: []//销毁列表
    }
    //注册命令
    const registry = (command) => {
        // 接受一个命令对象作为参数，
        // 将该命令对象添加到"state.commandArray"数组中，
        // 将命令名称与执行函数的映射关系添加到"state.commands"对象中。
        state.commandArray.push(command);
        // console.log(command);

        state.commands[command.name] = (...args) => {
            // console.log(state.commands);
            const { redo, undo } = command.execute(...args);
            // console.log(...args);
            redo()
            if (!command.pushQueue) {
                return
            }
            // debugger;
            let { queue, current } = state;
            if (queue.length > 0) {
                queue = queue.slice(0, current + 1)
                state.queue = queue
            }
            queue.push({ redo, undo })
            state.current = current + 1
            // console.log(queue);
        }
    }
    // 前进
    registry({
        name: 'redo',
        keyboard: 'ctrl+y',
        execute() {
            return {
                redo() {
                    let item = state.queue[state.current + 1]
                    if (item) {
                        item.redo && item.redo();
                        state.current++
                    }
                }
            }
        }
    })
    // 返回
    registry({
        name: 'undo',
        keyboard: 'ctrl+z',
        execute() {
            return {
                redo() {
                    if (state.current == -1) return;
                    let item = state.queue[state.current]
                    if (item) {
                        item.undo && item.undo();
                        state.current--
                    }
                }
            }
        }
    })
    // 记录拖拽
    registry({
        name: "drag",
        pushQueue: true,
        init() { //初始化操作 默认会执行
            this.before = null;
            const start = () => this.before = deepcopy(data.value.block)
            const end = () => state.commands.drag()
            events.on("start", start)
            events.on("end", end)
            return () => {
                events.off("start", start)
                events.off("end", end)
            }
        },
        execute() {
            let before = this.before;
            let after = data.value.block
            return {
                redo() {
                    data.value = { ...data.value, block: after }
                },
                undo() {
                    data.value = { ...data.value, block: before }
                }
            }
        }
    });
    // 设置页面大小
    registry({
        name: "updateContainer",
        pushQueue: true,
        execute(newValue) {
            let state = {
                before: data.value,
                after: newValue
            }
            return {
                redo: () => { data.value = state.after },
                undo: () => { data.value = state.before }
            }
        }
    })
    // 置顶
    registry({
        name: 'placeTop',
        pushQueue: true,
        execute() {
            let before = deepcopy(data.value.block)
            let after = (() => {
                let { focus, unfocus } = focusData.value
                const result = extractProperty(unfocus, 'zIndex')
                const maxZindex = Math.max(...result)
                focus.forEach(block => block.zIndex = maxZindex + 1)
                return data.value.block
            })()
            return {
                undo: () => { data.value = { ...data.value, block: before } },
                redo: () => { data.value = { ...data.value, block: after } },
            }
        }
    })
    // 置底
    registry({
        name: 'placeBottom',
        pushQueue: true,
        execute() {
            let before = deepcopy(data.value.block)
            let after = (() => {
                let { focus, unfocus } = focusData.value
                const result = extractProperty(unfocus, 'zIndex')
                const maxZindex = Math.max(...result)
                focus.forEach(block => block.zIndex = maxZindex - 1)
                return data.value.block
            })()
            return {
                undo: () => { data.value = { ...data.value, block: before } },
                redo: () => { data.value = { ...data.value, block: after } },
            }
        }
    })
    // 删除
    registry({
        name: 'delete',
        pushQueue: true,
        execute() {
            let before = deepcopy(data.value.block)
            let after = focusData.value.unfocus
            return {
                undo: () => { data.value = { ...data.value, block: before } },
                redo: () => { data.value = { ...data.value, block: after } },
            }
        }
    })
    const keyboardEvent = (() => {
        const keyCodes = {
            90: 'z',
            89: 'y'
        }
        const onKeydown = (e) => {
            const { ctrlKey, keyCode } = e
            let keyString = []
            if (ctrlKey) keyString.push('ctrl')
            keyString.push(keyCodes[keyCode])
            keyString = keyString.join('+');
            console.log(keyString);
            state.commandArray.forEach(({ keyboard, name }) => {
                if (!keyboard) return
                if (keyboard === keyString) {
                    state.commands[name]()
                    e.preventDefault()
                }
            })
        }
        const init = () => {
            window.addEventListener('keydown', onKeydown)
            return () => {
                window.removeEventListener('keydown', onKeydown)
            }
        }
        return init
    })();
    (() => {
        state.destoryArray.push(keyboardEvent())
        state.commandArray.forEach(command => command.init && state.destoryArray.push(command.init()))
    })()
    onUnmounted(() => {
        state.destoryArray.forEach(fn => fn && fn())
    })
    return state
}